﻿using Admin.NET.Core.Weapp;
using Furion;
using Furion.DatabaseAccessor;
using Furion.DataEncryption;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.Extras.Admin.NET;
using Furion.Extras.Admin.NET.Options;
using Furion.Extras.Admin.NET.Service;
using Furion.FriendlyException;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace Admin.NET.Core
{
    /// <summary>
    /// 小程序服务
    /// </summary>
    [ApiDescriptionSettings(Name = "Auth", Order = 160)]
    public class WeappService : IWeappService, IDynamicApiController, ITransient
    {
        static readonly long CLIENT_ROLE_ID = 142307070910560;
        static readonly long TENANT_ID = App.GetConfig<long>("TenantId", false);

        public WeappService(
            IRepository<SysUser> sysUserRep,
            IRepository<SysUserRole> sysUserRoleRep,
            IRepository<SysOuterUser> outerUserRep, IWeappApi weappApi,
            ISysEmpService sysEmpService,
            IHttpContextAccessor httpContextAccessor
        )
        {
            this._weappApi = weappApi;
            this._sysUserRep = sysUserRep;
            this._outerUserRep = outerUserRep;
            this._sysEmpService = sysEmpService;
            this._httpContextAccessor = httpContextAccessor;
            this._sysUserRoleRep = sysUserRoleRep;
        }

        private readonly IRepository<SysUser> _sysUserRep; // 用户表仓储
        private readonly IRepository<SysOuterUser> _outerUserRep;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IRepository<SysUserRole> _sysUserRoleRep;
        private readonly ISysEmpService _sysEmpService; // 系统员工服务
        private readonly IWeappApi _weappApi;

        [AllowAnonymous]
        [HttpGet("/weapplogin")]
        public async Task<string> LoginAsync(string code)
        {
            var session = await this._weappApi.Code2SessionAsync(code);
            var outerUser = this._outerUserRep.Where(p => p.Platform == OuterPlatform.Wechat && p.UnionId == session.UnionId && p.TenantId == TENANT_ID).FirstOrDefault();
            SysUser user;
            if (outerUser == null)
            {
                user = new SysUser
                {
                    Account = "wx" + session.UnionId,
                    Password = "",
                    Sex = Gender.UNKNOWN,
                    Status = CommonStatus.ENABLE,
                    TenantId = TENANT_ID
                };

                outerUser = new SysOuterUser
                {
                    Platform = OuterPlatform.Wechat,
                    UnionId = session.UnionId,
                    User = user,
                    TenantId = TENANT_ID
                };
                // 插入角色
                this._sysUserRoleRep.Insert(new SysUserRole
                {
                    SysUserId = user.Id,
                    SysRoleId = CLIENT_ROLE_ID
                });
                await this._outerUserRep.InsertAsync(outerUser);
            }
            else
            {
                user = _sysUserRep
                    .Where(u => u.Id == outerUser.UserId)
                    .FirstOrDefault();
            }

            if (user == null)
            {
                throw Oops.Oh(500);
            }

            // 验证账号是否被冻结
            if (user.Status == CommonStatus.DISABLE)
                throw Oops.Oh(ErrorCode.D1017);

            // 生成Token令牌
            //var accessToken = await _jwtBearerManager.CreateTokenAdmin(user);
            var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
            {
                {ClaimConst.CLAINM_USERID, user.Id},
                {ClaimConst.TENANT_ID, user.TenantId},
                {ClaimConst.CLAINM_ACCOUNT, user.Account},
                {ClaimConst.CLAINM_NAME, user.Name},
                {ClaimConst.CLAINM_SUPERADMIN, user.AdminType},
                {ClaimConst.CLAINM_CLIENTUSER, user.AdminType},
            });

            // 生成刷新Token令牌
            var refreshToken =
                JWTEncryption.GenerateRefreshToken(accessToken, App.GetOptions<RefreshTokenSettingOptions>().ExpiredTime);

            // 设置刷新Token令牌
            _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;
            return accessToken;
        }


        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="input"></param>
        /// <remarks>默认用户名/密码：admin/admin</remarks>
        /// <returns></returns>
        [HttpPost("/loginbindmp")]
        [AllowAnonymous]
        public async Task<string> LoginBindMpAsync([Required] LoginInput input)
        {
            // 获取加密后的密码
            var encryptPasswod = MD5Encryption.Encrypt(input.Password);

            // 判断用户名和密码是否正确 忽略全局过滤器
            var user = _sysUserRep
                .Where(u => u.Account.Equals(input.Account) && u.Password.Equals(encryptPasswod) && !u.IsDeleted, false, true)
                .FirstOrDefault();
            _ = user ?? throw Oops.Oh(ErrorCode.D1000);

            // 验证账号是否被冻结
            if (user.Status == CommonStatus.DISABLE)
                throw Oops.Oh(ErrorCode.D1017);

            try
            {
                //绑定微信OpenId
                var session = await this._weappApi.Code2SessionAsync(input.AccessToken);
                if (session.OpenId != null)
                {
                    var outerUser = this._outerUserRep.DetachedEntities.IgnoreQueryFilters().Where(p => p.Platform == OuterPlatform.Wechat && p.OpenId == session.OpenId && p.TenantId == TENANT_ID).FirstOrDefault();
                    if (outerUser == null)
                    {
                        outerUser = new SysOuterUser
                        {
                            Platform = OuterPlatform.Wechat,
                            UnionId = session.OpenId,
                            OpenId = session.OpenId,
                            UserId = user.Id,
                            TenantId = TENANT_ID
                        };
                        outerUser = (await this._outerUserRep.InsertAsync(outerUser)).Entity;
                    }
                }
            }
            catch (Exception ex)
            {

            }

            // 员工信息
            var empInfo = _sysEmpService.GetEmpInfo(user.Id).Result;

            // 生成Token令牌
            //var accessToken = await _jwtBearerManager.CreateTokenAdmin(user);
            var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
            {
                {ClaimConst.CLAINM_USERID, user.Id},
                {ClaimConst.TENANT_ID, user.TenantId},
                {ClaimConst.CLAINM_ACCOUNT, user.Account},
                {ClaimConst.CLAINM_NAME, user.Name},
                {ClaimConst.CLAINM_SUPERADMIN, user.AdminType},
                {ClaimConst.CLAINM_ORGID, empInfo.OrgId},
                {ClaimConst.CLAINM_ORGNAME, empInfo.OrgName},
            });

            // 设置Swagger自动登录
            _httpContextAccessor.HttpContext.SigninToSwagger(accessToken);

            // 生成刷新Token令牌
            var refreshToken =
                JWTEncryption.GenerateRefreshToken(accessToken, App.GetOptions<RefreshTokenSettingOptions>().ExpiredTime);

            // 设置刷新Token令牌
            _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;

            return accessToken;
        }


        /// <summary>
        /// 微信openId登录
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [HttpGet("/wxlogin")]
        [AllowAnonymous]
        public async Task<string> WxLogin(string code)
        {
            //绑定微信OpenId
            var session = await this._weappApi.Code2SessionAsync(code);
            if (session.OpenId != null)
            {
                var outerUser = this._outerUserRep.DetachedEntities.Include(u=>u.User).IgnoreQueryFilters().Where(p => p.Platform == OuterPlatform.Wechat && p.OpenId == session.OpenId && p.TenantId == TENANT_ID).FirstOrDefault();
                
                if (outerUser == null || outerUser.User==null)
                    throw Oops.Oh(ErrorCode.D1002);

                // 验证账号是否被冻结
                if (outerUser.User.Status == CommonStatus.DISABLE)
                    throw Oops.Oh(ErrorCode.D1017);

                // 员工信息
                var empInfo = _sysEmpService.GetEmpInfo(outerUser.User.Id).Result;

                // 生成Token令牌
                //var accessToken = await _jwtBearerManager.CreateTokenAdmin(user);
                var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
            {
                {ClaimConst.CLAINM_USERID, outerUser.User.Id},
                {ClaimConst.TENANT_ID, outerUser.User.TenantId},
                {ClaimConst.CLAINM_ACCOUNT, outerUser.User.Account},
                {ClaimConst.CLAINM_NAME, outerUser.User.Name},
                {ClaimConst.CLAINM_SUPERADMIN, outerUser.User.AdminType},
                {ClaimConst.CLAINM_ORGID, empInfo.OrgId},
                {ClaimConst.CLAINM_ORGNAME, empInfo.OrgName},
            });

                // 设置Swagger自动登录
                _httpContextAccessor.HttpContext.SigninToSwagger(accessToken);

                // 生成刷新Token令牌
                var refreshToken =
                    JWTEncryption.GenerateRefreshToken(accessToken, App.GetOptions<RefreshTokenSettingOptions>().ExpiredTime);

                // 设置刷新Token令牌
                _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;

                return accessToken;
            }
            else
            {
                throw Oops.Oh(ErrorCode.D1002);
            }
        }
    }
}
